package java8;

/**
 * @ProjectName random_code
 * @PackageName PACKAGE_NAME
 * @ClassName Java8Tester
 * @Description:
 * @author: Administrator
 * @Date: 2019/6/5 11:59
 * @Version 1.0
 */
public class Java8Tester {

    /*1.Lambda 表达式主要用来定义行内执行的方法类型接口
      2.Lambda 表达式免去了使用匿名方法的麻烦，并且给予Java简单但是强大的函数化的编程能力。
      3.接口类型可用来声明一个变量，他们可以成为一个空指针，或是被绑定在一个以此接口实现的对象*/

    /*1.接口不能用于实例化对象。
      2.接口没有构造方法。
      3.接口中所有的方法必须是抽象方法。
      4.接口不能包含成员变量，除了 static 和 final 变量。
      5.接口不是被类继承了，而是要被类实现。
      6.接口支持多继承。*/

    /*接口特性
      1.接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract（只能是 public abstract，其他修饰符都       会报错）。
      2.接口中可以含有变量，但是接口中的变量会被隐式的指定为 public static final 变量（并且只能是 public，用 private
        修饰会报编译错误）。
      3.接口中的方法是不能在接口中实现的，只能由实现接口的类来实现接口中的方法。
      4.接口是隐式抽象的，当声明一个接口的时候，不必使用abstract关键字。
      5.接口中每一个方法也是隐式抽象的，声明时同样不需要abstract关键字。
      6.接口中的方法都是公有的。*/

    /*接口和抽象类的区别
      1. 抽象类中的方法可以有方法体，就是能实现方法的具体功能，但是接口中的方法不行。
      2. 抽象类中的成员变量可以是各种类型的，而接口中的成员变量只能是 public static final 类型的。
      3. 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法)，而抽象类是可以有静态代码块和静态方法。
      4. 一个类只能继承一个抽象类，而一个类却可以实现多个接口。*/

    /*重写接口中声明的方法时，需要注意以下规则：
     1. 类在实现接口的方法时，不能抛出强制性异常，只能在接口中，或者继承接口的抽象类中抛出该强制性异常。
     2.类在重写方法时要保持一致的方法名，并且应该保持相同或者相兼容的返回值类型。
     3.如果实现接口的类是抽象类，那么就没必要实现该接口的方法。

     在实现接口的时候，也要注意一些规则：
     1.一个类可以同时实现多个接口。
     2.一个类只能继承一个类，但是能实现多个接口。
     3.一个接口能继承另一个接口，这和类之间的继承比较相似。*/

    /*没有任何方法的接口被称为标记接口。标记接口主要用于以下两种目的：
      建立一个公共的父接口：
      正如EventListener接口，这是由几十个其他接口扩展的Java API，你可以使用一个标记接口来建立一组接口的父接口。例如：当一
      个接口继承了EventListener接口，Java虚拟机(JVM)就知道该接口将要被用于一个事件的代理方案。
      向一个类添加数据类型:
      这种情况是标记接口最初的目的，实现标记接口的类不需要定义任何接口方法(因为标记接口根本就没有方法)，但是该类通过多态性变
      成一个接口类型。*/

    /*Lambda表达式允许将代码块作为方法的参数，允许使用更简洁的代码来创建只要一个抽象方法的接口的实例
    （这种接口称为函数式接口）
     从语法上看，lamdba表达式的主要作用就是代替匿名内部类的繁琐语法*/

    interface MathOperation {
        int operation(int a, int b);
    }

    interface GreetingService {
        void sayMessage(String message);
    }

    //针对只有一个抽象方法的接口,参数写接口类型
    private int operate(int a, int b, MathOperation mathOperation){
        return mathOperation.operation(a, b);
    }


    public static void main(String args[]){

            Java8Tester tester = new Java8Tester();

            // 类型声明 相当于一个接口的实现类
            MathOperation addition = (int a, int b) -> a + b;

            // 不用类型声明
            MathOperation subtraction = (a, b) -> a - b;

            // 大括号中的返回语句
            MathOperation multiplication = (int a, int b) -> { return a * b; };

            // 没有大括号及返回语句
            MathOperation division = (int a, int b) -> a / b;

            System.out.println("10 + 5 = " + tester.operate(10, 5, (c,d)->c+d));
            System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction));
            System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication));
            System.out.println("10 / 5 = " + tester.operate(10, 5, division));

            // 不用括号 相当于一个实现类
            GreetingService greetService1 = message ->
                    System.out.println("Hello " + message);

            // 用括号
            GreetingService greetService2 = (message) ->
                    System.out.println("Hello " + message);

            greetService1.sayMessage("Runoob");
            greetService2.sayMessage("Google");
        }

}
